﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using ProgNetDxComponents.ExtenderProviders.Language;
using ProgNetDxComponents.ExtenderProviders;

namespace ProgNetDxComponents.ExtenderProviders.Browsers
{
    public partial class BrowserForm : XtraForm
    {
        BaseEdit ValueMemberEdit = null;
        private Dictionary<BaseEdit, string> filters = new Dictionary<BaseEdit, string>();
        private DataView DataView = null;
        private bool IsTree = false;
        private List<BaseEdit> AllEdits = new List<BaseEdit>();
        public object EditValue
        {
            get;
            set;
        }

        public string DisplayFilter
        {
            get;
            set;
        }

        private bool AllowNew
        {
            get { return btnNew.Visible; }
            set { btnNew.Visible = value; }
        }

        private int numOfE = 0;
        private int numOfC = 0;

        public BrowserForm()
        {
            InitializeComponent();
        }

        private Browser _Browser;

        public void InitForm(Browser browser, bool AllowNew, object editValue)
        {
            DataView = new DataView(BrowserCache.GetBrowserData(browser.Name));
            DataView.RowFilter = DisplayFilter;

            _Browser = browser;
            this.Text = ProgNetLanguage.sGetStringDefault(_Browser.Name, _Browser.Name);
            this.AllowNew = AllowNew;
            this.EditValue = editValue;

            SearchPanel.Controls.Clear();
            SearchPanel.RowStyles.Clear();
            SearchPanel.ColumnStyles.Clear();
            SearchPanel.RowCount = 0;
            SearchPanel.ColumnCount = 0;
            IsTree = browser.IsTreeBrowser;
            if (IsTree)
            {
                MainTree.KeyFieldName = browser.ValueMember;
                MainTree.ParentFieldName = browser.ChildColumn;
                MainTree.DataSource = DataView;
                MainTree.Dock = DockStyle.Fill;
                gcMain.Visible = false;
            }
            else
            {
                gvMain.Columns.Clear();
                foreach (BrowserColumn c in _Browser.Columns)
                {
                    gvMain.Columns.Add(BrowserTools.CreateColumn(c, gvMain, this.browserProvider1));
                }
                gcMain.DataSource = DataView;
                for (int i = 0; i < gvMain.RowCount; i++)
                {
                    DataRow r = gvMain.GetDataRow(i);
                    if(r !=null)
                        if (r[browser.ValueMember].IsTheSame(editValue))
                        {
                            gvMain.FocusedRowHandle = i;
                            break;
                        }
                }
                BrowserTools.DisableGridCustomize(gvMain);
                gcMain.Dock = DockStyle.Fill;
                MainTree.Visible = false;
            }
            CountFields();
            AddButtons();
            CreateSearchFields();
        }

        private void AddButtons()
        {
            btnFind.Visible = false;
        }
        private void CreateSearchFields()
        {
            if ((numOfE + numOfC) > 0)
            {
                #region count rows and columns
                int eRowCount = 0;

                int aRowCount = 0;
                int aColCount = 1;
                if (numOfE > 0)
                    aColCount = 2;
                eRowCount = (int)(numOfE * 2 / aColCount) + ((numOfE * 2 % aColCount) > 0 ? 1 : 0);

                aRowCount = (int)((numOfC + numOfE * 2) / aColCount) + (((numOfC + numOfE * 2) % aColCount) > 0 ? 1 : 0);
                if (aRowCount > aColCount + 3)
                {
                    while (aRowCount > aColCount + 3)
                    {
                        if ((eRowCount * aColCount) <= aRowCount)
                            aColCount += 1;
                        else
                            aColCount += 2;
                        eRowCount = (int)(numOfE * 2 / aColCount) + ((numOfE * 2 % aColCount) > 0 ? 1 : 0);
                        aRowCount = (int)((numOfC + numOfE * 2) / aColCount) + (((numOfC + numOfE * 2) % aColCount) > 0 ? 1 : 0);
                    }
                }
                this.Width = aColCount * 155 + 110;
                SearchPanel.Height = aRowCount * 40 + 10;

                this.Height = SearchPanel.Height + 250;
                SearchPanel.RowCount = aRowCount;
                SearchPanel.ColumnCount = aColCount;
                for (int rs = 0; rs < aRowCount; rs++)
                {
                    SearchPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 35));
                }
                for (int cs = 0; cs < aColCount; cs++)
                {
                    SearchPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
                }
                #endregion

                int row = 0;
                int col = 0;
                int i = 0;
                #region Add text edits
                foreach (BrowserColumn column in _Browser.Columns)
                {
                    if (column.SearchField)
                    {
                        if (column.ColumnType !=  BrowserColumnType.CheckColumn)
                        {
                            if (row >= aRowCount)
                            {
                                row = 0;
                                col += 2;
                            }

                            BaseEdit Edit = CreateEdit(column);
                            Edit.EditValue = null;
                            LabelControl lbl = CreateLabel(column);
                            Edit.TabIndex = i;
                            i++;
                            if (i == 1)
                            {
                                Edit.Focus();
                                Edit.SelectAll();
                            }
                            SearchPanel.Controls.Add(lbl, col, row);
                            SearchPanel.Controls.Add(Edit, col + 1, row);
                            row += 1;
                        }
                    }
                }
                #endregion
                #region Add Checkboxes
                col = 0;
                row = 0;
                int startColIndex = 1;
                foreach (BrowserColumn column in _Browser.Columns)
                {
                    if (column.SearchField && column.ColumnType ==  BrowserColumnType.CheckColumn)
                    {
                        while (SearchPanel.GetControlFromPosition(col, row) != null)
                        {
                            col += 1;
                            if (col >= aColCount)
                            {
                                col = startColIndex;
                                row += 1;
                                if (row > aRowCount)
                                {
                                    startColIndex = 0;
                                    col = 0;
                                    row = 0;
                                }
                            }
                        }

                        BaseEdit Edit = CreateEdit(column);
                        i++;
                        Edit.TabIndex = i;
                        if (i == 1)
                        {
                            Edit.Focus();
                            Edit.SelectAll();
                        }
                        SearchPanel.Controls.Add(Edit, col, row);
                        col += 1;
                        if (col >= aColCount)
                        {
                            col = 0;
                            row += 1;
                        }
                    }
                }
                #endregion

                SearchPanel.Height = SearchPanel.RowCount * 40;
                this.Height = SearchPanel.RowCount * 40 + 300;
                if (this.Height > Screen.PrimaryScreen.WorkingArea.Height)
                    this.Height = Screen.PrimaryScreen.WorkingArea.Height;

                this.Width = SearchPanel.ColumnCount * 120 + panelButtons.Width;

                int wid = 0;
                foreach (BrowserColumn c in _Browser.Columns)
                    if (c.Visible)
                        wid += c.Width;
                if (Width < wid)
                    this.Width = wid;

                if (this.Width > Screen.PrimaryScreen.WorkingArea.Width)
                    this.Width = Screen.PrimaryScreen.WorkingArea.Width;
            }
            else
            {
                panelFilter.Visible = false;
            }
        }

        private void CountFields()
        {
            numOfE = 0;
            numOfC = 0;

            foreach (BrowserColumn col in _Browser.Columns)
            {
                if (col.SearchField)
                {
                    if (col.ColumnType == BrowserColumnType.CheckColumn)
                        numOfC++;
                    else
                        numOfE++;
                }
            }
        }

        private BaseEdit CreateEdit(BrowserColumn col)
        {
            BaseEdit e;
            switch (col.ColumnType)
            {
                case  BrowserColumnType.CheckColumn:
                    e = new CheckEdit();
                    e.Name = "Edit" + col.Name;
                    (e as CheckEdit).Properties.Appearance.TextOptions.WordWrap = DevExpress.Utils.WordWrap.Wrap;
                    BrowserTools.PrepareProperties((e as CheckEdit).Properties, col);
                    string caption = col.Caption;
                    if (caption.IsNull())
                        e.Text = ProgNetLanguage.sGetStringDefault(col.Name, col.Name);
                    else
                        e.Text = caption;
                    break;
                case BrowserColumnType.DateColumn:
                    e = new DateEdit();
                    e.Name = "Edit" + col.Name;
                    BrowserTools.PrepareProperties((e as DateEdit).Properties, col);
                    break;
                case BrowserColumnType.LookupColumn:
                    e = new LookUpEdit();
                    e.Name = "Edit" + col.Name;
                    BrowserTools.PrepareProperties((e as LookUpEdit).Properties, col);
                    if (col.BrowserName.IsNotNull())
                        browserProvider1.GetSettings(e).BrowserName = col.BrowserName;
                    break;/*
                case FieldType.GridLookUpEdit:
                    e = new GridLookUpEdit();
                    e.Name = "Edit" + col.Name;
                    BrowserTools.PrepareProperties((e as GridLookUpEdit).Properties, col);
                    if (StringExt.IsNotEmpty(col.BrowserName))
                        dataSourceProvider1.SetBrowserName(e, col.BrowserName);
                    if (col.Browser != null)
                        dataSourceProvider1.SetBrowser(e, col.Browser);
                    break;*/
                //case BrowserColumnType.CalcEdit:
                //    e = new CalcEdit();
                //    e.Name = "Edit" + col.Name;
                //    BrowserTools.PrepareProperties((e as CalcEdit).Properties, col);
                //    break;
                //case BrowserColumnType.SpinEdit:
                //    e = new SpinEdit();
                //    e.Name = "Edit" + col.Name;
                //    BrowserTools.PrepareProperties((e as SpinEdit).Properties, col);
                //    break;
                default:
                    e = new TextEdit();
                    e.Name = "Edit" + col.Name;
                    BrowserTools.PrepareProperties((e as TextEdit).Properties, col);
                    break;
            }
            if (col.Name == _Browser.ValueMember)
                ValueMemberEdit = e;
            e.KeyDown += new KeyEventHandler(e_KeyDown);
            e.Tag = col.Name;
            e.Properties.NullText = "";
            e.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
            //if (Browser.UseFilter)
                e.EditValueChanging += new DevExpress.XtraEditors.Controls.ChangingEventHandler(e_EditValueChanging);
            AllEdits.Add(e);
            return e;
        }
        private LabelControl CreateLabel(BrowserColumn col)
        {
            LabelControl lbl = null;
            if (col != null && col.ColumnType !=  BrowserColumnType.CheckColumn)
            {
                lbl = new LabelControl();
                lbl.Appearance.Options.UseTextOptions = true;
                lbl.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Far;
                lbl.Appearance.TextOptions.VAlignment = DevExpress.Utils.VertAlignment.Center;
                lbl.AutoSizeMode = DevExpress.XtraEditors.LabelAutoSizeMode.None;
                lbl.Dock = System.Windows.Forms.DockStyle.Fill;
                lbl.Name = "lbl" + col.Name;
                lbl.Size = new System.Drawing.Size(142, 29);
                lbl.TabIndex = 1;
                string caption = col.Caption;
                if (caption.IsNull())
                {
                    lbl.Text = ProgNetLanguage.sGetStringDefault(col.Name, col.Name);
                }
                else
                {
                    lbl.Text = caption;
                }
                if (!lbl.Text.EndsWith(":"))
                    lbl.Text += ":";
            }
            return lbl;
        }

        void e_KeyDown(object sender, KeyEventArgs e)
        {
            //if (!Browser.UseFilter)
            //{
            //    if (e.KeyCode == Keys.Enter)
            //    {
            //        btnFind.PerformClick();
            //    }
            //}
        }

        void e_EditValueChanging(object sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e)
        {
            //if (Browser.UseFilter)
            {
                BaseEdit ed = sender as BaseEdit;
                if (ed != null)
                {
                    if (filters.ContainsKey(ed))
                        filters[ed] = GetFiletr(ed, e.NewValue);
                    else
                        filters.Add(ed, GetFiletr(ed, e.NewValue));
                }
                ApplyFilter();
            }
        }
        
        private string GetFiletr(BaseEdit e, object val)
        {
            BrowserColumn col = _Browser.Columns[e.Tag.AsString()];
             string filter = "";
             if (val.IsNotNull())
             {
                 if (col != null)
                 {
                     switch (col.FilterCondition)
                     {
                         case FilterType.BeginsWith:
                             filter = col.Name + " LIKE '?%'";
                             break;
                         case FilterType.Bigger:
                             filter = col.Name + " > '?'";
                             break;
                         case FilterType.BiggerOrEqual:
                             filter = col.Name + " >= '?'";
                             break;
                         case FilterType.Contains:
                             filter = col.Name + " LIKE '%?%'";
                             break;
                         case FilterType.EndsWith:
                             filter = col.Name + " LIKE '%?'";
                             break;
                         case FilterType.Equal:
                             filter = col.Name + " = '?'";
                             break;
                         case FilterType.NotEqual:
                             filter = col.Name + " <> '?'";
                             break;
                         case FilterType.Smaller:
                             filter = col.Name + " < '?'";
                             break;
                         case FilterType.SmallerOrEqual:
                             filter = col.Name + " <= '?'";
                             break;
                     }
                     filter = filter.Replace("?", val.AsString().PrepareString());
                 }
             }
             return filter;
        }
        private string GetFiletr(BaseEdit e)
        {
            return GetFiletr(e, e.EditValue);
        }

        private void ApplyFilter()
        {
            string filter = DisplayFilter;
            //if (Browser.UseFilter)
            {
                foreach (string s in filters.Values)
                {
                    if (s.IsNotNull())
                    {
                        filter = filter.AppendAnd();
                        filter += "(" + s + ")";
                    }
                }
                DataView.RowFilter = filter;
            }
            
            if (IsTree)
                MainTree.RefreshDataSource();
            else
            {
                gcMain.RefreshDataSource();
            }
        }

        private void btnFind_Click(object sender, EventArgs e)
        {
            ApplyFilter();
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            filters.Clear();
            foreach (BaseEdit ed in AllEdits)
            {
                ed.Properties.LockEvents();
                ed.EditValue = _Browser.Columns[ed.Tag.AsString()].DefaultValue;
                filters.Add(ed, GetFiletr(ed));
                ed.Properties.UnLockEvents();
            }
            
            ApplyFilter();
        }

        private void btnNew_Click(object sender, EventArgs e)
        {
            EditValue = null;
            DialogResult = DialogResult.OK;
            Close();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            EditValue = GetEditValue();
            if (EditValue != null)
            {
                DialogResult = DialogResult.OK;
                Close();
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
            Close();
        }

        private object GetEditValue()
        {
            if (IsTree)
            {
                if (MainTree.FocusedNode != null)
                    MainTree.FocusedNode.GetValue(_Browser.ValueMember);
            }
            else
            {
                DataRow r = gvMain.GetFocusedDataRow();
                if (r != null)
                    return r[_Browser.ValueMember];
            }
            return null;
        }

        public ObjectDialogResult ShowDlg()
        {
            ObjectDialogResult res = new ObjectDialogResult();
            res.DialogResult = this.ShowDialog();
            if (res.DialogResult == System.Windows.Forms.DialogResult.OK)
                res.Value = this.EditValue;
            return res;
        }
        
    }
}
